﻿using MongoDB.Bson;
using MongoDB.Bson.Serialization.Serializers;
using MongoDB.Bson.Serialization;
using MongoDB.Driver;

namespace anydata.DataStorage
{
    public class MongoStorage : ISingleton
    {
        private readonly ILogger logger;
        private static bool Inited = false;
        private IMongoClient client;
        private static readonly Mutex mu = new Mutex();
        public MongoStorage(ILogger<MongoStorage> _logger)
        {
            logger = _logger;
        }

        public bool InitOnce()
        {
            if (Inited) return Inited;
            try
            {
                mu.WaitOne();
                if (!Inited)
                {
                    BsonSerializer.RegisterSerializer(DateTimeSerializer.LocalInstance);
                    client = new MongoClient(Config.DbConnectionString());
                    Inited = true;
                }
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "GetDatabase is error!");
            }
            finally
            {
                mu.ReleaseMutex();
            }
            return Inited;
        }

        public bool GetCollection<T>(TokenModel token, string collName,
            out IMongoCollection<T>? collection)
        {
            collection = default;
            if (InitOnce())
            {
                collection = client.GetDatabase(token.DbName).GetCollection<T>(collName);
            }
            return collection != default;
        }

        public async Task<BsonDocument?> RunCommandAsync(TokenModel token, BsonDocument command)
        {
            if (InitOnce())
            {
                return await client.GetDatabase(token.DbName).RunCommandAsync<BsonDocument>(command);
            }
            return default;
        }

        public async Task<List<string>?> ListCollectionsAsync(TokenModel token)
        {
            if (InitOnce())
            {
                return await (await client.GetDatabase(token.DbName).ListCollectionNamesAsync()).ToListAsync();
            }
            return default;
        }
    }
}
